package me.itsoo.artemis.framework.repository.mapper.condition;

import me.itsoo.artemis.framework.core.tuple.Pair;
import me.itsoo.artemis.framework.core.util.CollectionUtils;
import me.itsoo.artemis.framework.core.util.ReflectUtils;
import me.itsoo.artemis.framework.repository.mapper.MapperDefinition;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/**
 * ConditionSimpleFactory
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/5/18
 */
public class ConditionSimpleFactory {

    /**
     * 构建标准 QueryCondition
     *
     * @param md   MapperDefinition
     * @param cond T
     * @return QueryCondition
     */
    public <T> QueryCondition createQueryCondition(MapperDefinition md, T cond) {
        if (Objects.isNull(md)) {
            return null;
        }

        final List<Pair<String, Field>> pks = md.getPrimaryKeys();
        if (CollectionUtils.isNotEmpty(pks)) {
            final Pair<String, Field> pair1 = CollectionUtils.findFirstNonNull(pks);
            final QueryCondition result = QueryCondition.where(pair1.getKey()).eq(ReflectUtils.getFieldValue(pair1.getValue(), cond));

            for (int i = 1, len = pks.size(); i < len; i++) {
                final Pair<String, Field> pair2 = pks.get(i);
                result.and(pair2.getKey()).eq(ReflectUtils.getFieldValue(pair2.getValue(), cond));
            }

            return result;
        }

        return null;
    }

    /**
     * 构建标准 QueryCondition
     *
     * @param md     MapperDefinition
     * @param pkColl Collection
     * @return QueryCondition
     */
    public QueryCondition createQueryCondition(MapperDefinition md, Collection<?> pkColl) {
        if (Objects.isNull(md) || CollectionUtils.isEmpty(pkColl)) {
            return null;
        }

        final List<Pair<String, Field>> pks = md.getPrimaryKeys();
        if (CollectionUtils.isNotEmpty(pks)) {
            final Object[] pkArray = pkColl.toArray();
            final Pair<String, Field> pair1 = CollectionUtils.findFirstNonNull(pks);
            final QueryCondition result = QueryCondition.where(pair1.getKey());

            // 多条件下：生成前半部分查询条件
            Object value = pkArray[0];
            if (value instanceof Collection) {
                result.in(CollectionUtils.transform((Collection<?>) value, f -> ReflectUtils.getFieldValue(pair1.getValue(), f)));
            } else {
                result.eq(ReflectUtils.getFieldValue(pair1.getValue(), value));
            }
            if (pks.size() > 1) {
                appendAndQueryConditionWith(pks, result, value);
            }

            // 多条件下：拼接后半部分查询条件
            for (int i = 1; i < pkArray.length; i++) {
                result.or();

                value = pkArray[i];
                final Pair<String, Field> pair2 = CollectionUtils.findFirstNonNull(pks);
                if (value instanceof Collection) {
                    result.groupStart(pair2.getKey()).in(CollectionUtils.transform((Collection<?>) value, f -> ReflectUtils.getFieldValue(pair2.getValue(), f)));
                } else {
                    result.groupStart(pair2.getKey()).eq(ReflectUtils.getFieldValue(pair2.getValue(), value));
                }
                appendAndQueryConditionWith(pks, result, value);
                result.groupEnd();
            }

            return result;
        }

        return null;
    }

    /**
     * 拼接 and 条件
     *
     * @param pks    List
     * @param result QueryCondition
     * @param value  Object
     */
    private void appendAndQueryConditionWith(List<Pair<String, Field>> pks, QueryCondition result, Object value) {
        for (int j = 1, len = pks.size(); j < len; j++) {
            final Pair<String, Field> pair = pks.get(j);
            if (value instanceof Collection) {
                result.and(pair.getKey()).in(CollectionUtils.transform((Collection<?>) value, f -> ReflectUtils.getFieldValue(pair.getValue(), f)));
            } else {
                result.and(pair.getKey()).eq(ReflectUtils.getFieldValue(pair.getValue(), value));
            }
        }
    }
}
